﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Nine;
using BEPUphysics.DataStructures;
using BEPUphysics.Collidables;
using BEPUphysics.CollisionShapes.ConvexShapes;
using BEPUphysics.MathExtensions;
using LevelEditor.BepuTools;
using BEPUphysics.Entities.Prefabs;
using PerformanceUtility.GameDebugTools;

namespace LevelEditor.EditorSupport
{
    public static class InputComponents
    {
        public static float TranslateSpeed = 30.0f;
        public static float ScaleSpeed = 1.0f;
        public static float RotateSpeed = 1.0f;

        public static KeyboardState previousKeyboard;
        public static KeyboardState currentKeyboard;
        public static MouseState previousMouse;
        public static MouseState currentMouse;

        public static void HandleInput(GameTime gameTime)
        {
            InputComponents.previousKeyboard = InputComponents.currentKeyboard;
            InputComponents.currentKeyboard = Keyboard.GetState();
            InputComponents.previousMouse = InputComponents.currentMouse;
            InputComponents.currentMouse = Mouse.GetState();

            HandleEditorInput();

            HandleModelManipulation(gameTime);
        }

        private static void HandleEditorInput()
        {
            if ((InputComponents.currentKeyboard.IsKeyDown(Keys.O) && !InputComponents.previousKeyboard.IsKeyDown(Keys.O)) &&
                (InputComponents.currentKeyboard.IsKeyDown(Keys.LeftControl) || InputComponents.currentKeyboard.IsKeyDown(Keys.RightControl)))
            {
                LevelObjects.StillModels.Clear();
                Stack<int> toRemove = new Stack<int>();
                for (int i = 0; i < EditorComponents.Game.Components.Count; i++)
                {
                    if (EditorComponents.Game.Components[i].GetType() == typeof(StaticModel))
                    {
                        toRemove.Push(i);
                    }

                }

                for (int i = toRemove.Count; i > 0; i--)
                {
                    EditorComponents.Game.Components.RemoveAt(toRemove.Pop());
                }
                EditorComponents.LoadLevel(ref LevelObjects.StillModels, ref LevelObjects.EventBoxes, ref LevelObjects.EventSpheres, EditorComponents.Content, LevelObjects.LightView, LevelObjects.LightProjection);
            }
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.S) && !InputComponents.previousKeyboard.IsKeyDown(Keys.S))
            {
                if (InputComponents.currentKeyboard.IsKeyDown(Keys.LeftControl) || InputComponents.currentKeyboard.IsKeyDown(Keys.RightControl))
                {
                    EditorComponents.SaveLevel(LevelObjects.StillModels, LevelObjects.EventBoxes, LevelObjects.EventSpheres);
                }
                else
                {
                    for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                    {
                        LevelObjects.SelectedModels[i].DisplayShadow = !LevelObjects.SelectedModels[i].DisplayShadow;
                    }
                }
            }
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.Delete) && !InputComponents.previousKeyboard.IsKeyDown(Keys.Delete))
            {
                for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                {
                    EditorComponents.space.Remove(LevelObjects.SelectedModels[i].Mesh);
                    LevelObjects.StillModels.Remove(LevelObjects.SelectedModels[i]);
                    LevelObjects.SelectedModels.Remove(LevelObjects.SelectedModels[i]);
                }

                LevelObjects.SelectedModels.Clear();
            }

            // Switch draw mode
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.F1) && !InputComponents.previousKeyboard.IsKeyDown(Keys.F1))
            {
                LevelObjects.DrawModels = !LevelObjects.DrawModels;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.F2) && !InputComponents.previousKeyboard.IsKeyDown(Keys.F2))
            {
                LevelObjects.DrawBounds = !LevelObjects.DrawBounds;

                // Only add if not already added
                if (LevelObjects.DrawBounds)
                {
                    for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                    {
                        if (!LevelObjects.StillModels[i].GenerateCollisionMesh)
                            continue;

                        //Make it visible too.
                        EditorComponents.Game.Components.Add(new StaticModel(LevelObjects.StillModels[i].XnaModel, LevelObjects.StillModels[i].WorldMatrix, EditorComponents.Game));
                    }
                }
                // Only add if not already added
                else
                {
                    Stack<int> toRemove = new Stack<int>();
                    for (int i = 0; i < EditorComponents.Game.Components.Count; i++)
                    {
                        if (EditorComponents.Game.Components[i].GetType() == typeof(StaticModel))
                        {
                            toRemove.Push(i);
                        }

                    }

                    for (int i = toRemove.Count; i > 0; i--)
                    {
                        EditorComponents.Game.Components.RemoveAt(toRemove.Pop());
                    }
                }
                
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.F3) && !InputComponents.previousKeyboard.IsKeyDown(Keys.F3))
            {
                LevelObjects.DrawEvents = !LevelObjects.DrawEvents;
            }

            // Switch movement mode
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.D1))
            {
                LevelObjects.MoveMode = ModelMovementMode.Rotate;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.D2))
            {
                LevelObjects.MoveMode = ModelMovementMode.Scale;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.D3))
            {
                LevelObjects.MoveMode = ModelMovementMode.Translate;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.D4))
            {
                LevelObjects.MoveMode = ModelMovementMode.PlaceCollisionBox;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.D5))
            {
                LevelObjects.MoveMode = ModelMovementMode.PlaceCollisionSphere;
            }

            // Change selected items
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.Left) && !InputComponents.previousKeyboard.IsKeyDown(Keys.Left))
            {
                LevelObjects.SelectedModelIndex--;
                if (LevelObjects.SelectedModelIndex < 0)
                    LevelObjects.SelectedModelIndex = LevelObjects.SelectedModels.Count - 1;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.Right) && !InputComponents.previousKeyboard.IsKeyDown(Keys.Right))
            {
                LevelObjects.SelectedModelIndex++;
                if (LevelObjects.SelectedModelIndex > LevelObjects.SelectedModels.Count - 1)
                    LevelObjects.SelectedModelIndex = 0;
            }
            else if (InputComponents.currentKeyboard.IsKeyDown(Keys.Enter) && !InputComponents.previousKeyboard.IsKeyDown(Keys.Enter))
            {
                // Get specifically the current index of multiple selected models
                if (LevelObjects.SelectedModels.Count > 0)
                {
                    string id = LevelObjects.SelectedModels[LevelObjects.SelectedModelIndex].ID;
                    LevelObjects.SelectedModelIndex = 0;
                    LevelObjects.SelectedModels.Clear();
                    for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                    {
                        if (id == LevelObjects.StillModels[i].ID)
                        {
                            LevelObjects.SelectedModels.Add(LevelObjects.StillModels[i]);
                            break;
                        }
                    }
                }

            }

            // Update generation of collision meshes
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.B) && !InputComponents.previousKeyboard.IsKeyDown(Keys.B))
            {
                for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                {
                    LevelObjects.SelectedModels[i].GenerateCollisionMesh = !LevelObjects.SelectedModels[i].GenerateCollisionMesh;

                    // add or remove as necessary
                    if (LevelObjects.SelectedModels[i].GenerateCollisionMesh)
                    {
                        LevelObjects.SelectedModels[i].Box = EditorComponents.CreateBoundingBox(LevelObjects.SelectedModels[i].NineModel, LevelObjects.SelectedModels[i].WorldMatrix); // Rotation requires the box to be entirely reconstructed

                        Vector3[] staticTriangleVertices;
                        int[] staticTriangleIndices;

                        TriangleMesh.GetVerticesAndIndicesFromModel(LevelObjects.SelectedModels[i].NineModel, out staticTriangleVertices, out staticTriangleIndices);

                        var staticMesh = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(LevelObjects.SelectedModels[i].Scale, Quaternion.CreateFromRotationMatrix(Matrix.CreateRotationX(LevelObjects.SelectedModels[i].Rotation.X) * Matrix.CreateRotationY(LevelObjects.SelectedModels[i].Rotation.Y) * Matrix.CreateRotationZ(LevelObjects.SelectedModels[i].Rotation.Z)), LevelObjects.SelectedModels[i].Position));
                        staticMesh.Sidedness = TriangleSidedness.Counterclockwise;

                        staticMesh.Tag = LevelObjects.SelectedModels[i].ID;

                        // Add to the space
                        LevelObjects.SelectedModels[i].Mesh = staticMesh;
                        EditorComponents.space.Add(LevelObjects.SelectedModels[i].Mesh);

                        if (LevelObjects.DrawBounds)
                        {
                            EditorComponents.Game.Components.Add(new StaticModel(LevelObjects.SelectedModels[i].XnaModel, LevelObjects.SelectedModels[i].WorldMatrix, EditorComponents.Game));
                        }
                    }
                    else
                    {
                        // Remove the mesh
                        EditorComponents.space.Remove(LevelObjects.SelectedModels[i].Mesh);
                        // Hack: remove and readd all drawing components (See outside the loop)
                    }
                }

                // Hack from above: remove and readd where appropriate
                if (LevelObjects.DrawBounds)
                {
                    // Remove all 
                    Stack<int> toRemove = new Stack<int>();
                    for (int i = 0; i < EditorComponents.Game.Components.Count; i++)
                    {
                        if (EditorComponents.Game.Components[i].GetType() == typeof(StaticModel))
                        {
                            toRemove.Push(i);
                        }

                    }
                    for (int i = toRemove.Count; i > 0; i--)
                    {
                        EditorComponents.Game.Components.RemoveAt(toRemove.Pop());
                    }

                    // readd where appropriate
                    // Only add if not already added
                    for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                    {
                        if (!LevelObjects.StillModels[i].GenerateCollisionMesh)
                            continue;

                        //Make it visible too.
                        EditorComponents.Game.Components.Add(new StaticModel(LevelObjects.StillModels[i].XnaModel, LevelObjects.StillModels[i].WorldMatrix, EditorComponents.Game));
                    }
                }

                // Remove objects
                Stack<int> toRemove2 = new Stack<int>();
                for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                {
                    // Remove if no bounds and no display
                    if (!LevelObjects.StillModels[i].DisplayModel && !LevelObjects.StillModels[i].GenerateCollisionMesh)
                    {
                        toRemove2.Push(i);
                    }
                }

                for (int i = toRemove2.Count; i > 0; i--)
                {
                    int removing = toRemove2.Pop();
                    EditorComponents.space.Remove(LevelObjects.StillModels[removing].Mesh);
                    LevelObjects.StillModels.RemoveAt(removing);
                }
            }

            // Handle whether drawing graphically or not
            if (InputComponents.currentKeyboard.IsKeyDown(Keys.G) && !InputComponents.previousKeyboard.IsKeyDown(Keys.G))
            {
                Stack<int> toRemove = new Stack<int>();

                for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                {
                    LevelObjects.SelectedModels[i].DisplayModel = !LevelObjects.SelectedModels[i].DisplayModel;
                }

                // Remove objects
                for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                {
                    // Remove if no bounds and no display
                    if (!LevelObjects.StillModels[i].DisplayModel && !LevelObjects.StillModels[i].GenerateCollisionMesh)
                    {
                        toRemove.Push(i);
                    }
                }

                for (int i = toRemove.Count; i > 0; i--)
                {
                    int removing = toRemove.Pop();
                    try
                    {
                        EditorComponents.space.Remove(LevelObjects.StillModels[removing].Mesh);
                    }
                    catch (Exception)
                    {
                    }
                    finally
                    {
                        LevelObjects.StillModels.RemoveAt(removing);
                    }
                }
            }
        }

        private static void HandleModelManipulation(GameTime gameTime)
        {
            // Get selected items
            if (InputComponents.currentMouse.LeftButton == ButtonState.Pressed && InputComponents.previousMouse.LeftButton == ButtonState.Released)
            {
                LevelObjects.SelectedModels.Clear();
                LevelObjects.SelectedModelIndex = 0;
                Ray r = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);

                float minDist = float.MaxValue; //EditorComponents.FreeCamera.MaxRadius;
                for (int i = 0; i < LevelObjects.StillModels.Count; i++)
                {
                    float? f = r.Intersects(LevelObjects.StillModels[i].Box);
                    if (f != null)
                    {
                        // Insert according to distance
                        if (f.Value < minDist)
                        {
                            minDist = f.Value;
                            LevelObjects.SelectedModels.Insert(0, LevelObjects.StillModels[i]);
                        }
                        else
                        {
                            LevelObjects.SelectedModels.Add(LevelObjects.StillModels[i]);
                        }
                    }
                }
            }

            switch (LevelObjects.MoveMode)
            {
                case ModelMovementMode.Rotate:
                    // Change increment speed
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemPlus))
                    {
                        RotateSpeed += (float)gameTime.ElapsedGameTime.TotalSeconds;
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemMinus))
                    {
                        RotateSpeed -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (RotateSpeed <= 0.0f)
                            RotateSpeed = 0.0001f;
                    }

                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad1))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z - RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                            while (LevelObjects.SelectedModels[i].Rotation.Z < -MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z + MathHelper.TwoPi);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad5))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X - RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z);
                            while (LevelObjects.SelectedModels[i].Rotation.X < -MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X + MathHelper.TwoPi, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad3))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z + RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                            while (LevelObjects.SelectedModels[i].Rotation.Z > MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z - MathHelper.TwoPi);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad4))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y - RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Rotation.Z);
                            while (LevelObjects.SelectedModels[i].Rotation.X < -MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y + MathHelper.TwoPi, LevelObjects.SelectedModels[i].Rotation.Z);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad2))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X + RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z);
                            while (LevelObjects.SelectedModels[i].Rotation.X > MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X - MathHelper.TwoPi, LevelObjects.SelectedModels[i].Rotation.Y, LevelObjects.SelectedModels[i].Rotation.Z);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad6))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y + RotateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Rotation.Z);
                            while (LevelObjects.SelectedModels[i].Rotation.Y > MathHelper.TwoPi)
                            {
                                LevelObjects.SelectedModels[i].Rotation = new Vector3(LevelObjects.SelectedModels[i].Rotation.X, LevelObjects.SelectedModels[i].Rotation.Y - MathHelper.TwoPi, LevelObjects.SelectedModels[i].Rotation.Z);
                            }
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad8))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Rotation = Vector3.Zero;
                        }
                    }
                    break;
                case ModelMovementMode.Scale:
                    // Change increment speed
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemPlus))
                    {
                        ScaleSpeed += (float)gameTime.ElapsedGameTime.TotalSeconds;
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemMinus))
                    {
                        ScaleSpeed -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (ScaleSpeed <= 0.0f)
                            ScaleSpeed = 0.0001f;
                    }

                    // Uniform Scale by Keyboard
                    if (!DebugSystem.Instance.DebugCommandUI.Focused)
                    {
                        if (InputComponents.currentKeyboard.IsKeyDown(Keys.Up))
                        {
                            for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                            {
                                LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds,
                                    LevelObjects.SelectedModels[i].Scale.Y + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds,
                                    LevelObjects.SelectedModels[i].Scale.Z + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                            }
                        }
                        else if (InputComponents.currentKeyboard.IsKeyDown(Keys.Down))
                        {
                            for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                            {
                                LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds,
                                    LevelObjects.SelectedModels[i].Scale.Y - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds,
                                    LevelObjects.SelectedModels[i].Scale.Z - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                            }
                        }
                    }

                    // Axis scale by keyboard
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad1))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Scale.Y, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad2))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(1.0f, LevelObjects.SelectedModels[i].Scale.Y, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad3))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Scale.Y, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad4))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, LevelObjects.SelectedModels[i].Scale.Y - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad5))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, 1.0f, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad6))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, LevelObjects.SelectedModels[i].Scale.Y + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Scale.Z);
                        }
                    }
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad7))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, LevelObjects.SelectedModels[i].Scale.Y, LevelObjects.SelectedModels[i].Scale.Z - ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad8))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, LevelObjects.SelectedModels[i].Scale.Y, 1.0f);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad9))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Scale = new Vector3(LevelObjects.SelectedModels[i].Scale.X, LevelObjects.SelectedModels[i].Scale.Y, LevelObjects.SelectedModels[i].Scale.Z + ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                        }
                    }

                    // Uniform Scale by Mouse
                    //if (InputComponents.currentMouse.LeftButton == ButtonState.Pressed)
                    //{
                    //    for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                    //    {
                    //        LevelObjects.SelectedModels[i].Scale += LevelObjects.SelectedModels[i].Scale * ScaleSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds * (previousMouse.Y - currentMouse.Y);
                    //    }
                    //}
                    break;
                case ModelMovementMode.Translate:
                    // Change increment speed
                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemPlus))
                    {
                        TranslateSpeed += (float)gameTime.ElapsedGameTime.TotalSeconds;
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.OemMinus))
                    {
                        TranslateSpeed -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                        if (TranslateSpeed <= 0.0f)
                            TranslateSpeed = 0.0001f;
                    }

                    if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad1))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X - TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Position.Y, LevelObjects.SelectedModels[i].Position.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad4))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X, LevelObjects.SelectedModels[i].Position.Y - TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Position.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad3))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X + TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Position.Y, LevelObjects.SelectedModels[i].Position.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad5))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X, LevelObjects.SelectedModels[i].Position.Y, LevelObjects.SelectedModels[i].Position.Z - TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad6))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X, LevelObjects.SelectedModels[i].Position.Y + TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds, LevelObjects.SelectedModels[i].Position.Z);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad2))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = new Vector3(LevelObjects.SelectedModels[i].Position.X, LevelObjects.SelectedModels[i].Position.Y, LevelObjects.SelectedModels[i].Position.Z + TranslateSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
                        }
                    }
                    else if (InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad8))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            LevelObjects.SelectedModels[i].Position = Vector3.Zero;
                        }
                    }
                    break;
                case ModelMovementMode.PlaceCollisionBox:
                    if (LevelObjects.EditingHeight)
                    {
                        if (currentMouse.LeftButton == ButtonState.Pressed && previousMouse.LeftButton == ButtonState.Released)
                        {
                            LevelObjects.EditingHeight = false;

                            // Fix max/min overlaps that may occur while placing
                            Vector3 max = LevelObjects.CreateMax;
                            Vector3 min = LevelObjects.CreateMin;

                            max.Y = MathHelper.Max(LevelObjects.CreateMax.Y, LevelObjects.CreateMin.Y);
                            min.Y = MathHelper.Min(LevelObjects.CreateMin.Y, LevelObjects.CreateMax.Y);

                            // Add for tracking
                            LevelObjects.EventBoxes.Add(new BoundingBox(min, max));
                            LevelObjects.CreateMax = LevelObjects.CreateMin = Vector3.Zero;
                        }
                    }
                    else if (LevelObjects.EditingWidthLength)
                    {
                        if (previousMouse.LeftButton == ButtonState.Pressed && currentMouse.LeftButton == ButtonState.Released)
                        {
                            LevelObjects.EditingWidthLength = false;
                            LevelObjects.EditingHeight = true;
                        }
                    }
                    else
                    {
                        if (currentMouse.LeftButton == ButtonState.Pressed && previousMouse.LeftButton == ButtonState.Released)
                        {
                            LevelObjects.EditingWidthLength = true;
                        }
                    }

                    if (LevelObjects.EditingWidthLength)
                    {
                        if (currentMouse.LeftButton == ButtonState.Pressed)
                        {

                            // Creating a new box, else expanding an existing box
                            if (previousMouse.LeftButton == ButtonState.Released)
                            {
                                LevelObjects.SelectedModels.Clear();
                                LevelObjects.SelectedModelIndex = 0;

                                Ray ray = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);
                                Plane p = new Plane(Vector3.UnitY, 0.0f);

                                float? distToPlane = ray.Intersects(p);

                                if (distToPlane != null)
                                {
                                    LevelObjects.CreateMin = new Vector3(ray.Direction.X * distToPlane.Value + ray.Position.X, 0, ray.Direction.Z * distToPlane.Value + ray.Position.Z);
                                    LevelObjects.CreateMax = new Vector3(ray.Direction.X * distToPlane.Value + ray.Position.X, 1, ray.Direction.Z * distToPlane.Value + ray.Position.Z);
                                }
                            }
                            else
                            {
                                Ray ray = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);
                                Plane p = new Plane(Vector3.UnitY, 0.0f);

                                float? distToPlane = ray.Intersects(p);

                                if (distToPlane != null)
                                {
                                    LevelObjects.CreateMax = new Vector3(ray.Direction.X * distToPlane.Value + ray.Position.X, 1, ray.Direction.Z * distToPlane.Value + ray.Position.Z);
                                }
                            }
                        }
                    }
                    else if (LevelObjects.EditingHeight)
                    {
                        // Fix max/min overlaps that may occur while placing
                        Vector3 max = LevelObjects.CreateMax;
                        Vector3 min = LevelObjects.CreateMin;

                        max.X = MathHelper.Max(LevelObjects.CreateMax.X, LevelObjects.CreateMin.X);
                        max.Z = MathHelper.Max(LevelObjects.CreateMax.Z, LevelObjects.CreateMin.Z);
                        min.X = MathHelper.Min(LevelObjects.CreateMin.X, LevelObjects.CreateMax.X);
                        min.Z = MathHelper.Min(LevelObjects.CreateMin.Z, LevelObjects.CreateMax.Z);

                        LevelObjects.CreateMax = max;
                        LevelObjects.CreateMin = min;

                        // if it was down and now up, change z (up/down values)
                        Ray ray = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);
                        Plane p = new Plane(-Vector3.UnitZ, (LevelObjects.CreateMax.Z + LevelObjects.CreateMin.Z) / 2);

                        float? distToPlane = ray.Intersects(p);

                        if (distToPlane != null)
                        {
                            LevelObjects.CreateMax = new Vector3(LevelObjects.CreateMax.X, ray.Direction.Y * distToPlane.Value + ray.Position.Y, LevelObjects.CreateMax.Z);
                        }
                    }
                    break;
                case ModelMovementMode.PlaceCollisionSphere:
                    // Start creating a new sphere
                    if (currentMouse.LeftButton == ButtonState.Pressed)
                    {
                        // Create the new sphere for editing
                        if (previousMouse.LeftButton == ButtonState.Released)
                        {
                            LevelObjects.SelectedModels.Clear();
                            LevelObjects.SelectedModelIndex = 0;

                            Ray ray = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);
                            Plane p = new Plane(Vector3.UnitY, 0.0f);

                            float? distToPlane = ray.Intersects(p);

                            if (distToPlane != null)
                            {
                                LevelObjects.CreateCenter = new Vector3(ray.Direction.X * distToPlane.Value + ray.Position.X, 0, ray.Direction.Z * distToPlane.Value + ray.Position.Z);
                                LevelObjects.CreateRadius = 1.0f;
                            }
                        }
                        // Adjust the radius of the sphere
                        else
                        {
                            // if it was down and now up, change z (up/down values)
                            Ray ray = EditorComponents.Game.GraphicsDevice.Viewport.CreatePickRay(Mouse.GetState().X, Mouse.GetState().Y, EditorComponents.Camera.View, EditorComponents.Camera.Projection);
                            Plane p = new Plane(-Vector3.UnitZ, LevelObjects.CreateCenter.Z);

                            float? distToPlane = ray.Intersects(p);

                            if (distToPlane != null)
                            {
                                LevelObjects.CreateRadius = MathHelper.Clamp(ray.Direction.Y * distToPlane.Value + ray.Position.Y, 1.0f, 100000.0f);
                            }
                        }
                    }
                    // Finalize the sphere
                    else if (previousMouse.LeftButton == ButtonState.Pressed)
                    {
                        LevelObjects.EventSpheres.Add(new BoundingSphere(LevelObjects.CreateCenter, LevelObjects.CreateRadius));

                        LevelObjects.CreateCenter = Vector3.Zero;
                        LevelObjects.CreateRadius = 0.0f;
                    }
                    break;
                default:
                    break;
            }

            // Group common functions here, even if we have to call switch/if multiple times
            switch (LevelObjects.MoveMode)
            {
                case ModelMovementMode.Rotate:
                case ModelMovementMode.Scale:
                case ModelMovementMode.Translate:
                        if (InputComponents.currentKeyboard.IsKeyDown(Keys.Up) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.Down) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad1) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad2) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad3) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad4) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad5) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad6) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad7) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad8) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad9) ||
                        InputComponents.currentKeyboard.IsKeyDown(Keys.NumPad0))
                    {
                        for (int i = 0; i < LevelObjects.SelectedModels.Count; i++)
                        {
                            if (!LevelObjects.SelectedModels[i].GenerateCollisionMesh)
                                continue;

                            LevelObjects.SelectedModels[i].Box = EditorComponents.CreateBoundingBox(LevelObjects.SelectedModels[i].NineModel, LevelObjects.SelectedModels[i].WorldMatrix); // Rotation requires the box to be entirely reconstructed

                            EditorComponents.space.Remove(LevelObjects.SelectedModels[i].Mesh);

                            Vector3[] staticTriangleVertices;
                            int[] staticTriangleIndices;

                            TriangleMesh.GetVerticesAndIndicesFromModel(LevelObjects.SelectedModels[i].NineModel, out staticTriangleVertices, out staticTriangleIndices);

                            var staticMesh = new StaticMesh(staticTriangleVertices, staticTriangleIndices, new AffineTransform(LevelObjects.SelectedModels[i].Scale, Quaternion.CreateFromRotationMatrix(Matrix.CreateRotationX(LevelObjects.SelectedModels[i].Rotation.X) * Matrix.CreateRotationY(LevelObjects.SelectedModels[i].Rotation.Y) * Matrix.CreateRotationZ(LevelObjects.SelectedModels[i].Rotation.Z)), LevelObjects.SelectedModels[i].Position));
                            staticMesh.Sidedness = TriangleSidedness.Counterclockwise;

                            staticMesh.Tag = LevelObjects.SelectedModels[i].ID;

                            // Add to the space
                            LevelObjects.SelectedModels[i].Mesh = staticMesh;
                            EditorComponents.space.Add(LevelObjects.SelectedModels[i].Mesh);
                        }
                    }
                    break;
            }
        }
    }
}
